package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.PmsPurchaseRequisitionsDetailMapper;
import com.ruoyi.system.mapper.WmsSuppliersMapper;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.IWmsInboundService;
import com.ruoyi.system.utils.EmailUtil;
import com.ruoyi.system.utils.PurchaseOrderPdfGenerator;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.system.domain.bo.PmsPurchaseOrdersBo;
import com.ruoyi.system.domain.vo.PmsPurchaseOrdersVo;
import com.ruoyi.system.mapper.PmsPurchaseOrdersMapper;
import com.ruoyi.system.service.IPmsPurchaseOrdersService;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.MessagingException;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 采购订单主，记录采购订单核心信息Service业务层处理
 *
 * @author ruoyi
 * @date 2025-07-29
 */
@RequiredArgsConstructor
@Service
public class PmsPurchaseOrdersServiceImpl implements IPmsPurchaseOrdersService {

    private final PmsPurchaseOrdersMapper baseMapper;

    private final ISysUserService sysUserService;

    private final PmsPurchaseRequisitionsDetailMapper pmsPurchaseRequisitionsDetailMapper;

    private final WmsSuppliersMapper wmsSuppliersMapper;

    private final IWmsInboundService wmsInboundService;

    @Value("${ruoyi.profile}")
    private String path;

    /**
     * 查询采购订单主，记录采购订单核心信息
     */
    @Override
    public PmsPurchaseOrdersVo queryById(Long poId){
        return baseMapper.selectVoById(poId);
    }

    /**
     * 查询采购订单主，记录采购订单核心信息列表
     */
    @Override
    public TableDataInfo<PmsPurchaseOrdersVo> queryPageList(PmsPurchaseOrdersBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PmsPurchaseOrders> lqw = buildQueryWrapper(bo);
        Page<PmsPurchaseOrdersVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);


        List<PmsPurchaseOrdersVo> records = result.getRecords();

        // 1. 收集所有订单ID
        List<Long> prIds = records.stream()
            .map(PmsPurchaseOrdersVo::getPrId)
            .collect(Collectors.toList());

        List<PmsPurchaseRequisitionsDetail> pmsPurchaseRequisitionsDetails = pmsPurchaseRequisitionsDetailMapper.selectPmsPurchaseRequisitionsDetailListByIds(prIds);

        Map<Long, List<PmsPurchaseRequisitionsDetail>> detailsMap = pmsPurchaseRequisitionsDetails.stream()
            .collect(Collectors.groupingBy(PmsPurchaseRequisitionsDetail::getPurchaseRequistionsId));

        for (PmsPurchaseOrdersVo record : records) {
            record.setCreateNickName(sysUserService.selectUserById(record.getCreatedBy()).getNickName());
            if(ObjectUtil.isNotNull(record.getPurchaseId())){
                record.setPurchaseNickName(sysUserService.selectUserById(record.getPurchaseId()).getNickName());
            }

            // 设置订单明细（从Map中取）
            List<PmsPurchaseRequisitionsDetail> details = detailsMap.get(record.getPrId());
            record.setPmsPurchaseRequisitionsDetails(details != null ? details : new ArrayList<>());
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询采购订单主，记录采购订单核心信息列表
     */
    @Override
    public List<PmsPurchaseOrdersVo> queryList(PmsPurchaseOrdersBo bo) {
        LambdaQueryWrapper<PmsPurchaseOrders> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PmsPurchaseOrders> buildQueryWrapper(PmsPurchaseOrdersBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PmsPurchaseOrders> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getPoCode()), PmsPurchaseOrders::getPoCode, bo.getPoCode());
        lqw.eq(bo.getPrId() != null, PmsPurchaseOrders::getPrId, bo.getPrId());
        lqw.eq(StringUtils.isNotBlank(bo.getPrCode()), PmsPurchaseOrders::getPrCode, bo.getPrCode());
        lqw.eq(bo.getSupplierId() != null, PmsPurchaseOrders::getSupplierId, bo.getSupplierId());
        lqw.eq(StringUtils.isNotBlank(bo.getSupplierCode()), PmsPurchaseOrders::getSupplierCode, bo.getSupplierCode());
        lqw.between(params.get("beginOrderDate") != null && params.get("endOrderDate") != null,
            PmsPurchaseOrders::getOrderDate ,params.get("beginOrderDate"), params.get("endOrderDate"));
        lqw.eq(bo.getExpectedDeliveryDate() != null, PmsPurchaseOrders::getExpectedDeliveryDate, bo.getExpectedDeliveryDate());
        lqw.eq(StringUtils.isNotBlank(bo.getPaymentTerms()), PmsPurchaseOrders::getPaymentTerms, bo.getPaymentTerms());
        lqw.eq(bo.getTotalAmount() != null, PmsPurchaseOrders::getTotalAmount, bo.getTotalAmount());
        lqw.eq(bo.getTotalTax() != null, PmsPurchaseOrders::getTotalTax, bo.getTotalTax());
        lqw.eq(bo.getTotalAmountWithTax() != null, PmsPurchaseOrders::getTotalAmountWithTax, bo.getTotalAmountWithTax());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), PmsPurchaseOrders::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getApproverId()), PmsPurchaseOrders::getApproverId, bo.getApproverId());
        lqw.eq(bo.getApprovedAt() != null, PmsPurchaseOrders::getApprovedAt, bo.getApprovedAt());
        lqw.eq(ObjectUtil.isNotNull(bo.getCreatedBy()), PmsPurchaseOrders::getCreatedBy, bo.getCreatedBy());
        lqw.eq(bo.getCreateTime() != null, PmsPurchaseOrders::getCreateTime, bo.getCreateTime());
        lqw.eq(bo.getUpdatedAt() != null, PmsPurchaseOrders::getUpdatedAt, bo.getUpdatedAt());
        // 按 status 升序（ASC），createTime 降序（DESC）排序
        lqw.orderByAsc(PmsPurchaseOrders::getStatus)
            .orderByDesc(PmsPurchaseOrders::getCreateTime);

        return lqw;
    }

    /**
     * 新增采购订单主，记录采购订单核心信息
     */
    @Override
    public Boolean insertByBo(PmsPurchaseOrdersBo bo) {
        PmsPurchaseOrders add = BeanUtil.toBean(bo, PmsPurchaseOrders.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setPoId(add.getPoId());
        }
        return flag;
    }

    /**
     * 修改采购订单主，记录采购订单核心信息
     */
    @Override
    public Boolean updateByBo(PmsPurchaseOrdersBo bo) {
        bo.setPurchaseId(LoginHelper.getUserId());


        if("3".equals(bo.getStatus())){
            bo.setReceivingTime(new Date());
        }


        PmsPurchaseOrders update = BeanUtil.toBean(bo, PmsPurchaseOrders.class);

        if("4".equals(bo.getStatus())){
            //需要去入库表中插入数据，类型改为采购入库
            PmsPurchaseOrders pmsPurchaseOrders = addInBound(bo);
            update.setInboundOrderNo(pmsPurchaseOrders.getInboundOrderNo());
            update.setInboundId(pmsPurchaseOrders.getInboundId());
        }



        if("2".equals(bo.getStatus())){
            //生成采购订单pdf文件
            String pdfPath = generatePurchaseOrderPdf(bo.getPoId());

            update.setPdfPath(pdfPath);
        }

        validEntityBeforeSave(update);

        int i = baseMapper.updateById(update);



        return  i > 0;
    }

    /**
     * 生成采购订单PDF
     */
    public String generatePurchaseOrderPdf(Long poId) {
        // 1. 查询数据
        PmsPurchaseOrders order = baseMapper.selectById(poId);
        WmsSuppliers supplier = wmsSuppliersMapper.selectWmsSuppliersById(order.getSupplierId());
        List<Long> ids = new ArrayList<>();
        ids.add(order.getPrId());
        List<PmsPurchaseRequisitionsDetail> items = pmsPurchaseRequisitionsDetailMapper.selectPmsPurchaseRequisitionsDetailListByIds(ids);

        // 2. 生成PDF
        String pdfPath = path +"/poPdf/"+ order.getPoCode() + ".pdf";
        try {
            PurchaseOrderPdfGenerator.generatePurchaseOrderPdf(order, supplier, items, pdfPath);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 3. 可附加发送邮件逻辑（参考之前的邮件发送代码）
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String  deliveryDate = sdf.format(order.getExpectedDeliveryDate());
            String subject = "采购订单确认 - " + order.getPoCode() + "（请于" + deliveryDate + "前交货）";



            EmailUtil.sendEmailWithAttachment(
                "1264048157@qq.com",
                subject,
                getContent(order,supplier),
                pdfPath
            );
        } catch (MessagingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return pdfPath;
    }

    @Transactional
    public PmsPurchaseOrders addInBound(PmsPurchaseOrdersBo bo){

        PmsPurchaseOrders update = new PmsPurchaseOrders();

        String inboundOrderNo = wmsInboundService.getInboundOrderNo().getInboundOrderNo();
        WmsInbound wmsInbound = new WmsInbound();

        wmsInbound.setInboundOrderNo(inboundOrderNo);
        //采购入库
        wmsInbound.setInboundType("1");
        wmsInbound.setInboundStatus("2");
        wmsInbound.setSupplierId(bo.getSupplierId());
        wmsInbound.setOrderNo(bo.getPoCode());

        PmsPurchaseRequisitionsDetail pmsPurchaseRequisitionsDetail = new PmsPurchaseRequisitionsDetail();
        pmsPurchaseRequisitionsDetail.setPurchaseRequistionsId(bo.getPrId());
        List<PmsPurchaseRequisitionsDetail> pmsPurchaseRequisitionsDetailList = pmsPurchaseRequisitionsDetailMapper.selectPmsPurchaseRequisitionsDetailList(pmsPurchaseRequisitionsDetail);

        //合计金额
        BigDecimal totalAmount = pmsPurchaseRequisitionsDetailList.stream()
            .map(PmsPurchaseRequisitionsDetail::getPurchasePrice)  // 提取 BigDecimal 值
            .filter(Objects::nonNull)  // 过滤掉 null 值
            .reduce(BigDecimal.ZERO, BigDecimal::add);  // 从 0 开始累加

        wmsInbound.setTotalAmount(totalAmount);


        long totalQuantity = pmsPurchaseRequisitionsDetailList.stream()
            .mapToLong(PmsPurchaseRequisitionsDetail::getTotalQuantity)
            .sum();
        wmsInbound.setTotalQuantity(totalQuantity);

        wmsInbound.setInboundUserId(LoginHelper.getUserId());

        wmsInbound.setRemark(bo.getNickName()+"申请的采购订单，待入库");




        List<WmsInventoryHistory> wmsInventoryHistoryList = new ArrayList<>();

        for (PmsPurchaseRequisitionsDetail purchaseRequisitionsDetail : pmsPurchaseRequisitionsDetailList) {
            WmsInventoryHistory wmsInventoryHistory = new WmsInventoryHistory();
            wmsInventoryHistory.setProductId(purchaseRequisitionsDetail.getProductId());
            wmsInventoryHistory.setTotalQuantity(purchaseRequisitionsDetail.getTotalQuantity().longValue());
            wmsInventoryHistory.setTotalAmount(purchaseRequisitionsDetail.getPurchasePrice());
            wmsInventoryHistoryList.add(wmsInventoryHistory);
        }

        wmsInbound.setInventoryHistoryList(wmsInventoryHistoryList);

        try {
            wmsInboundService.insertWmsInbound(wmsInbound);
            update.setInboundId(wmsInbound.getId());
            update.setInboundOrderNo(wmsInbound.getInboundOrderNo());
            return update;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    String getContent(PmsPurchaseOrders order,WmsSuppliers supplier){

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 创建HTML格式的邮件正文（更专业美观）
        StringBuilder emailContent = new StringBuilder();
        emailContent.append("<html><body style=\"font-family: Arial, sans-serif; line-height: 1.6;\">");
        emailContent.append("<h2 style=\"color: #2c3e50;\">尊敬的" + supplier.getSupplierName() + "：</h2>");
        emailContent.append("<p>我司正式采购订单（编号：<strong>" + order.getPoCode() + "</strong>）已生成，详情如下：</p>");

// 订单基本信息表格
        emailContent.append("<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\" style=\"border-collapse: collapse; width: 100%; margin-bottom: 20px;\">");
        emailContent.append("<tr style=\"background-color: #f2f2f2;\"><th colspan=\"2\">订单基本信息</th></tr>");
        emailContent.append("<tr><td width=\"30%\"><strong>订单日期</strong></td><td>" + sdf.format(order.getOrderDate()) + "</td></tr>");
        emailContent.append("<tr><td><strong>预计交货日期</strong></td><td>" + sdf.format(order.getExpectedDeliveryDate()) + "</td></tr>");
        emailContent.append("<tr><td><strong>交货地址</strong></td><td>"+supplier.getAddress()+"</td></tr>");
        emailContent.append("<tr><td><strong>付款条款</strong></td><td>" + (order.getPaymentTerms() != null ? order.getPaymentTerms() : "货到30天内付款") + "</td></tr>");
        emailContent.append("<tr><td><strong>订单总额</strong></td><td>¥" + order.getTotalAmount() + "（含税）</td></tr>");
        emailContent.append("</table>");

// 注意事项
        emailContent.append("<h3 style=\"color: #2c3e50; margin-top: 20px;\">注意事项：</h3>");
        emailContent.append("<ul>");
        emailContent.append("<li>请严格按约定日期交货，逾期将按合同条款处理</li>");
        emailContent.append("<li>随货请提供<strong>增值税专用发票</strong>（发票信息见附件）</li>");
        emailContent.append("<li>包装需符合ISO标准，外箱需标注订单编号</li>");
        emailContent.append("<li>如有问题请联系采购专员："+ LoginHelper.getNickName() +" "+sysUserService.selectUserById(LoginHelper.getUserId()).getPhonenumber()+" </li>");
        emailContent.append("</ul>");

        emailContent.append("<p style=\"margin-top: 30px;\">此邮件为系统自动发送，请勿直接回复。</p>");
        emailContent.append("</body></html>");

        return emailContent.toString();
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PmsPurchaseOrders entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除采购订单主，记录采购订单核心信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
